/******************************************************************************
 Copyright (c) 2024-2025 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

******************************************************************************/

#include "gatt_ras_server_private.h"

#ifdef INSTALL_CHANNEL_SOUNDING_SUPPORT
#include "gatt_ras_server_debug.h"
#include "gatt_ras_server_msg_handler.h"
#include "csr_bt_cm_lib.h"

RasServiceHandleType ras_service_handle;

/****************************************************************************/
RasServiceHandleType GattRasServerInit(AppTask appTask, uint16 startHandle, uint16 endHandle, uint32 rasFeatures)
{
     GRASS_T *rasServer = NULL;
     uint8 i;

    /* validate the input parameters */
    if (appTask == CSR_SCHED_QID_INVALID)
    {
        GATT_RAS_SERVER_PANIC(
                    "RAS: Invalid Initialization parameters!"
                    );
    }

    ras_service_handle = ServiceHandleNewInstance((void **) &rasServer, sizeof(GRASS_T));
    GATT_RAS_SERVER_INFO("RAS: GattRasServerInit ras_service_handle 0x%x, rasServer 0x%p\n\n", ras_service_handle, rasServer);

    if (rasServer)
    {
        /* Reset all the service library memory */
        memset(rasServer, 0, sizeof(GRASS_T));

        /* Set up library handler for external messages */
        rasServer->libTask = GATT_RAS_SERVER_IFACEQUEUE;

        /* Store the Task function parameter.
         * All library messages need to be sent here */
        rasServer->appTask = appTask;

        /* Save the service handle */
        rasServer->srvcHndl = ras_service_handle;

        /* Initiliasation of the RAS Server Charateristics */

        memset(rasServer->data.connectedClients, 0, (sizeof(ras_client_data) * GATT_RAS_MAX_CONNECTIONS));

        /* Reset the client config value to default GATT_PACS_SERVER_INVALID_CLIENT_CONFIG */
        for(i = 0; i < GATT_RAS_MAX_CONNECTIONS; i++)
        {
            rasServer->data.connectedClients[i].clientCfg.realTimeDataClientCfg = GATT_RAS_SERVER_CCC_NONE;
            rasServer->data.connectedClients[i].clientCfg.onDemandDataClientCfg = GATT_RAS_SERVER_CCC_NONE;
            rasServer->data.connectedClients[i].clientCfg.controlPointClientCfg = GATT_RAS_SERVER_CCC_NONE;
            rasServer->data.connectedClients[i].clientCfg.dataReadyClientCfg = GATT_RAS_SERVER_CCC_NONE;
            rasServer->data.connectedClients[i].clientCfg.dataOverwrittenClientCfg = GATT_RAS_SERVER_CCC_NONE;
        }

        /* Setup data required for Ranging Service
         * to be registered with the GATT
         */
        rasServer->startHandle = startHandle;
        rasServer->endHandle = endHandle;

        rasServer->data.rasFeaturesMask = rasFeatures;

        /* Register with the GATT  and verify the result */
        rasServer->gattId = CsrBtGattRegister(rasServer->libTask);

        if (rasServer->gattId != CSR_BT_GATT_INVALID_GATT_ID)
        {
            CsrBtGattFlatDbRegisterHandleRangeReqSend(rasServer->gattId,
                                                     startHandle,
                                                     endHandle);

            /* Register with CM to receive Sub event and Sub event continue IND */
            CsrBtCmRegisterHandlerReqSend(CSR_BT_CM_HANDLER_TYPE_CS, GATT_RAS_SERVER_IFACEQUEUE , 0);

            /* Register with CM to receive CM_EVENT_MASK_SUBSCRIBE_CHANNEL_SOUNDING_IND */
            CsrBtCmSetEventMaskReqSend(GATT_RAS_SERVER_IFACEQUEUE, CM_EVENT_MASK_SUBSCRIBE_CHANNEL_SOUNDING_IND, CSR_BT_CM_EVENT_MASK_COND_ALL);
            return ras_service_handle;
        }
        else
        {
            /* If the registration with GATT Manager fails and we have allocated memory
             * for the new instance successfully (service handle not zero), we have to free
             * the memory of that instance.
             */
            if (ras_service_handle)
            {
                ServiceHandleFreeInstanceData(ras_service_handle);
            }
            return 0;
        }
    }
    else
    {
        GATT_RAS_SERVER_PANIC("Memory alllocation of RAS Server instance failed!\n");
        return 0;
    }
}

void gattRasServerInit(void** gash)
{
    *gash = &ras_service_handle;
    GATT_RAS_SERVER_INFO("Ras: gatt_ras_server_init\n\n");

}

#ifdef ENABLE_SHUTDOWN
void gattRasServerDeinit(void** gash)
{
    ServiceHandle serviceHandle = *((ServiceHandle*)*gash);
    ras_ranging_data_list *rangingList;
    GRASS_T* rasServer = ServiceHandleGetInstanceData(serviceHandle);
    CsrUint8 client_index;

    if (serviceHandle)
    {
        for (client_index = 0; client_index < GATT_RAS_MAX_CONNECTIONS; client_index++)
        {
            rangingList = rasServer->data.connectedClients[client_index].rangingDataList;
            while(rangingList != NULL)
            {
                rangingList = rasServer->data.connectedClients[client_index].rangingDataList->next;

                CsrPmemFree(rasServer->data.connectedClients[client_index].rangingDataList->data);
                CsrPmemFree(rasServer->data.connectedClients[client_index].rangingDataList);
                rasServer->data.connectedClients[client_index].rangingDataList = rangingList;
            }
        }
        if(ServiceHandleFreeInstanceData(serviceHandle))
        {
            GATT_RAS_SERVER_INFO("RAS: gatt_ras_server_deinit\n\n");
        }
        else
        {
            GATT_RAS_SERVER_PANIC("RAS: deinit - Unable to free RAS server instance.\n");
        }
    }
    else
    {
        GATT_RAS_SERVER_INFO("RAS: deinit - Invalid Service Handle\n\n");
    }
}

#endif /* ENABLE_SHUTDOWN */

#endif /* INSTALL_CHANNEL_SOUNDING_SUPPORT */
